#ifndef SPL_DATAOBJECT
#define SPL_DATAOBJECT

////////////////////////////////////////////////////////////////////////////////
// Based on dataobject.cpp by J Brown (www.catch22.net)

class DataObject : public IDataObject {
private:
    #pragma region Declarations
    LONG m_lRefCount;			// reference count
    FORMATETC *m_pFormatEtc;	// formats
    STGMEDIUM *m_pStgMedium;	// storage medium
    LONG m_nNumFormats;			// format count
    #pragma endregion

    #pragma region Helper Methods
    int LookupFormatEtc(FORMATETC *pFormatEtc);
    #pragma endregion

public:
    #pragma region IUnknown
    // Retrieves pointers to the supported interfaces on an object
    HRESULT WINAPI QueryInterface(REFIID iid, void **ppvObjectOut);
    // Increments the reference count for an interface on an object
    ULONG WINAPI AddRef();
    // Decrements the reference count for an interface on an object
    ULONG WINAPI Release();
    #pragma endregion

    #pragma region IDataObject
    // Called by a data consumer to obtain data from a source data object
    HRESULT WINAPI GetData(FORMATETC *pFormatEtc, STGMEDIUM *pMediumOut);
    // Called by a data consumer to obtain data from a source data object
    // This method differs from the GetData method in that the caller must
    // allocate and free the specified storage medium
    HRESULT WINAPI GetDataHere(FORMATETC *pFormatEtc,
        STGMEDIUM *pMediumOut);
    // Determines whether the data object is capable of rendering the
    // data as specified
    HRESULT WINAPI QueryGetData(FORMATETC *pFormatEtc);
    // Provides a potentially different but logically equivalent
    // FORMATETC structure
    HRESULT WINAPI GetCanonicalFormatEtc(FORMATETC *pFormatEtc,
        FORMATETC *pFormatEtcOut);
    // Called by an object containing a data source to transfer data to
    // the object that implements this method
    HRESULT WINAPI SetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium,
        BOOL fRelease);
    // Creates an object to enumerate the formats supported by a data object
    HRESULT WINAPI EnumFormatEtc(DWORD dwDirection,
        IEnumFORMATETC **ppEnumFormatEtcOut);
    // Creates a connection between a data object and an advise sink so
    // the advise sink can receive notifications of changes in the
    // data object
    HRESULT WINAPI DAdvise(FORMATETC *pFormatEtc, DWORD advf,
        IAdviseSink *pAdvSink, DWORD *pwdConnectionOut);
    // Destroys a notification previously set up with the DAdvise method
    HRESULT WINAPI DUnadvise(DWORD dwConnection);
    // Creates and returns a pointer to an object to enumerate the
    // current advisory connections
    HRESULT WINAPI EnumDAdvise(IEnumSTATDATA **ppEnumAdviseOut);
    #pragma endregion

    #pragma region Constructors & Destructors
    DataObject(FORMATETC *fmEtc, STGMEDIUM *stgMedium, int count);
    ~DataObject();
    #pragma endregion
};

#endif